# 列表常用方法与内置函数
# 列表的方法sort()或者内置函数sorted()可以完成排序操作。
# 对lst本身进行升序排列，使用sort()方法
lst = [3, 1, 2]
# lst变为[1, 2, 3]
lst.sort()

# 得到一个新的升序列表，lst保持不变，使用sorted()内置函数
lst = [3, 1, 2]
# lst不变，lst_sorted为[1, 2, 3]
lst_sorted = sorted(lst)
# 注意：无论是方法sort()或者内置函数sorted()都有两个形参，reverse和key，
# 前者表示是否倒序排列，后者表示排序的依据，通常会涉及到lambda匿名函数的使用
# 对lst本身进行降序排列，使用sort()方法
lst = [3, 1, 2]
# lst变为[3, 2, 1]
lst.sort(reverse = True)

# 得到一个新的降序列表，lst保持不变，使用sorted()内置函数
lst = [3, 1, 2]
# lst不变，lst_sorted为[3, 2, 1]
lst_sorted = sorted(lst, reverse = True)

#列表的方法reverse()或者内置函数reversed()可以完成翻转操作。
# 对lst本身进行翻转，使用reverse()方法
lst = [3, 1, 2]
# lst变为[2, 1, 3]
lst.reverse()

# 得到一个新的翻转列表，lst保持不变，使用reversed()内置函数
lst = [3, 1, 2]
# lst不变，lst_reversed为[2, 1, 3]
lst_reversed = list(reversed(lst))
# 也可以使用列表的切片操作来完成翻转，设置步长为-1即可。
# 得到一个新的翻转列表，lst保持不变，使用切片操作
lst = [3, 1, 2]
lst_reversed = lst[::-1]

# 如果想把一个列表里的所有元素批量地调用某一个函数，并映射得到一个新的列表（原列表中元素相对位置不变），可以使用内置函数map(func, iter)。
# map(func, iter)的含义是，对可迭代对象iter（通常是一个列表）里的所有元素都调用函数func，并得到一个新的map对象。如果我们对map对象的外部再调用list()，则可以得到一个新的列表。
lst_str = ["1", "2", "3"]
# 得到lst_num为[1, 2, 3]
lst_num = list(map(int, lst_str))
# 字符串中的split(x)方法以字符串x为分割符，将原字符串分割为一个新的列表并返回，原字符串不发生改变。如果不传入参数x，
# 则默认为按照空格" "进行分割。最常用的分隔符为空格" "或者逗号","。
s = "1 2 3 4 5"
lst = s.split()
# 等价于lst = s.split(" ")

s = "1,2,3,4,5"
lst = s.split(",")

# 两种分割均会得到lst = ["1", "2", "3", "4", "5"]
# 字符串中的join(lst)方法以原字符串为合并符，将列表lst合并为一个新的字符串并返回。
# 注意lst中的元素必须是字符串。最常用的合并符为空字符串""、空格字符串" "、逗号","。
lst = ["a", "b", "c"]
s = "".join(lst)
# 会得到s = "abc"

s_space = " ".join(lst)
# 会得到s_space = "a b c"

s_star = "*".join(lst)
# 会得到s_star = "a*b*c"
# 字符串的分割与合并是一对相互对应的操作，常用于列表与字符串之间的相互转换。
# 注意:
# 1. 字符串属于一种不可变数据类型，并不能直接进行修改操作。当题目要求对一个字符串进行修改时，通常会先将原字符串使用split()方法或list()转化成列表，对列表修改后再使用join()方法得到新字符串的方式来实现。
# 2. 列表lst必须是一个字符串类型列表，即lst: List[str]。如果lst是一个整数类型列表，直接使用语句"".join(lst)会出现类型错误TypeError。如需进行合并操作，必须使用map()内置函数对lst中的元素进行类型转换，将lst中的所有int类型元素转换成str类型。

"""
列表的切片（slice）是一个非常强大且实用的功能，可以非常灵活地获取列表中的子集，得到一个新的列表，使得处理列表数据更加方便和高效。其基本语法形如
列表切片 = 列表名[起始索引:终止索引:步长]
在上述语法中，我们使用起始索引:终止索引:步长来指定切片的范围。其中
- 起始索引：表示切片的开始位置，该位置的元素是能取得到的。
- 终止索引：表示切片的结束位置，该位置的元素是不能取到的。
- 步长：表示间隔的大小，默认为1。
譬如，我们想得到列表my_list中索引0到索引4的所有元素所构成的列表，其代码如下
lst = [1, 3, 5, 7, 9, 11]
sub_lst = lst[0:5:1]
print(sub_lst)
"""
# 又譬如，我们想得到列表my_list中索引0、2、4的所有元素所构成的列表，我们可以将步长设置为2，其代码如下
lst = [1, 3, 5, 7, 9, 11]
sub_lst = lst[0:6:2]
print(sub_lst)

# 当我们所选取的步长为1的时候，步长这个参数是可以被省略的。譬如
lst = [1, 3, 5, 7, 9, 11]
sub_lst1 = lst[0:5:]
sub_lst2 = lst[0:5]
print(sub_lst1)
print(sub_lst2)

#当我们希望切片包含原列表的第一个元素的时候，起始索引这个参数是可以被省略的。
lst = [1, 3, 5, 7, 9, 11]
sub_lst = lst[:5:2]
print(sub_lst)

#当我们希望切片包含原列表的最后一个元素的时候，终止索引这个参数是可以被省略的
lst = [1, 3, 5, 7, 9, 11]
sub_lst = lst[1::2]
print(sub_lst)

#这三个参数是可以同时省略的。
# 当我们只保留步长参数时，我们能够得到原列表中从头开始到末尾结束，按照步长为间隔所取的子列表。譬如
lst = [1, 3, 5, 7, 9, 11]
sub_lst1 = lst[::2]
sub_lst2 = lst[::3]
print(sub_lst1)
# [1, 5, 9]
print(sub_lst2)
# [1, 7]

#当我们三个参数都不保留时，我们得到了和原列表内容完全一致的一个新的列表。
lst = [1, 3, 5, 7, 9, 11]
sub_lst1 = lst[::]
sub_lst2 = lst[:]
print(sub_lst1)
print(sub_lst2)

#切片的负索引用于从列表末尾开始计数，这和列表的负索引的含义是一致的。
lst = [1, 3, 5, 7, 9, 11]
sub_lst = lst[-5:-2]
print(sub_lst)
# [3, 5, 7]

#切片的负步长用于对原列表进行反向切片。
lst = [1, 3, 5, 7, 9, 11]
sub_lst = lst[4:1:-1]
print(sub_lst)
# [9, 7, 5]

"""
相比起直接使用索引取列表中的值时，索引需要严格落在列表长度范围内，切片操作中对于起始索引和终止索引范围的选择则非常宽容。
即使所选取的起始索引和终止索引在原数组中取不到，也不会发生报错。
lst = [1, 3, 5, 7, 9, 11]
sub_lst1 = lst[10:]
sub_lst2 = lst[:10]
print(sub_lst1)
print(sub_lst2)
# []
# [1, 3, 5, 7, 9, 11]
"""